<template>
  <view class="progress-container" :style="containerStyle">
    <view class="progress-bar" :style="progressBarStyle"></view>
  </view>
</template>

<script setup lang="ts">
import { progressProps } from './types'
import type { ProgressColor } from './types'
const props = defineProps(progressProps)
// 当前进度
const currentProgress = ref(0)
// 当前颜色 默认 #4CAF50
const currentColor = ref('#4CAF50')

/**
 *
 * @param color 颜色配置
 * @returns 当前颜色
 */
const normalizeColors = (color: string | ProgressColor[]): ProgressColor[] => {
  if (typeof color === 'string') {
    return [{ color, progress: 0 }]
  }
  // 空数组 返回默认吗颜色
  if (Array.isArray(color) && color.length === 0) {
    return [{ color: '#4CAF50', progress: 0 }]
  }
  // 如果是有效数组 排序
  if (Array.isArray(color)) {
    // 这里[...color]是为了防止原数组被修改
    return [...color].sort((a, b) => a.progress - b.progress)
  }
  // 其他情况返回默认颜色
  return [{ color: '#4CAF50', progress: 0 }]
}

/**
 * 计算当前进度对应的颜色
 * @param progress 当前进度 (0-100)
 * @param colors 颜色配置数组
 * @returns 计算出的颜色值
 */
const calculateProgressColor = (progress: number, colors: ProgressColor[]): string => {
  // 如果只有一个颜色停止点，直接返回该颜色
  if (colors.length === 1) return colors[0].color

  // 如果当前的进度条小于第一个颜色的进度 返回第一个
  if (progress <= colors[0].progress) return colors[0].color

  // 如果当前的进度大于第一个颜色的进度 返回最后一个
  if (progress >= colors[colors.length - 1].progress) return colors[colors.length - 1].color
  // 检查在哪个区间
  for (let i = 0; i < colors.length - 1; i++) {
    const currentProgress = colors[i].progress
    const nextProgress = colors[i + 1].progress
    if (progress >= currentProgress && progress <= nextProgress) {
      // 进度差
      const range = nextProgress - currentProgress
      // 进度百分比
      const ratio = (progress - currentProgress) / range
      // 用来计算差值颜色
      return interpolateColor(colors[i].color, colors[i + 1].color, ratio)
    }
  }
}
/**
 * 颜色插值计算 (HEX格式)
 * @param color1 起始颜色
 * @param color2 结束颜色
 * @param ratio 混合比例 (0-1)
 * @returns 插值后的颜色
 */
const interpolateColor = (color1: string, color2: string, ratio: number): string => {
  // 解析HEX颜色
  const r1 = parseInt(color1.substring(1, 3), 16)
  const g1 = parseInt(color1.substring(3, 5), 16)
  const b1 = parseInt(color1.substring(5, 7), 16)

  const r2 = parseInt(color2.substring(1, 3), 16)
  const g2 = parseInt(color2.substring(3, 5), 16)
  const b2 = parseInt(color2.substring(5, 7), 16)

  // 计算插值
  const r = Math.round(r1 + (r2 - r1) * ratio)
  const g = Math.round(g1 + (g2 - g1) * ratio)
  const b = Math.round(b1 + (b2 - b1) * ratio)

  // 转回HEX格式
  return `#${((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1)}`
}

// 容器样式
const containerStyle = computed(() => {
  return {
    height: typeof props.height === 'number' ? `${props.height}px` : props.height,
    backgroundColor: props.containerBgColor,
    borderRadius:
      typeof props.borderRadius === 'number' ? `${props.borderRadius}px` : props.borderRadius,
  }
})

const progressBarStyle = computed(() => {
  const baseStyle: Record<string, string> = {
    width: `${currentProgress.value}%`,
    backgroundColor: currentColor.value,
    transition: `width ${props.transitionDuration}ms ease, background-color ${props.colorTransitionDuration}ms ease`,
    height: '100%',
  }
  // 条纹效果
  if (props.striped) {
    baseStyle.backgroundImage = `linear-gradient(
      45deg,
      rgba(255, 255, 255, 0.15) 25%,
      transparent 25%,
      transparent 50%,
      rgba(255, 255, 255, 0.15) 50%,
      rgba(255, 255, 255, 0.15) 75%,
      transparent 75%,
      transparent
    )`
    baseStyle.backgroundSize = '1rem 1rem'
  }
  // 条纹动画
  if (props.animated && props.striped) {
    baseStyle.animation = 'progress-bar-stripes 1s linear infinite'
  }
  return baseStyle
})
onMounted(() => {
  currentProgress.value = props.progress
  const normalColors = normalizeColors(props.color)
  currentColor.value = calculateProgressColor(props.progress, normalColors)
})
// 监听progress变化
watch(
  () => props.progress,
  (newVal) => {
    currentProgress.value = newVal
    const normalColors = normalizeColors(props.color)
    currentColor.value = calculateProgressColor(newVal, normalColors)
  },
)
</script>

<style lang="scss" scoped></style>
